package com.zznode.redsun.smartcrm.business.service.impl;

import java.sql.ResultSet;
import java.sql.SQLException;
import java.util.ArrayList;
import java.util.Calendar;
import java.util.Collection;

import net.sf.json.JSONObject;

import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.jdbc.core.RowMapper;
import org.springframework.stereotype.Service;
import org.springframework.util.Assert;
import org.springframework.util.StringUtils;

import com.zznode.csp.domain.commons.persistence.EntityManager;
import com.zznode.csp.domain.commons.query.JdbcFinderManager;
import com.zznode.csp.domain.commons.query.Page;
import com.zznode.csp.domain.commons.util.MapCreaterBuilder;
import com.zznode.redsun.commons.dto.CustomerDto;
import com.zznode.redsun.commons.dto.CustomerQuery;
import com.zznode.redsun.commons.sercurity.shiro.LoginUser;
import com.zznode.redsun.commons.utils.GlobalUtils;
import com.zznode.redsun.smartcrm.business.service.CustomerService;
import com.zznode.redsun.smartcrm.business.service.JdbcDictService;
import com.zznode.redsun.smartcrm.model.CardCategory;
import com.zznode.redsun.smartcrm.model.Customer;
import com.zznode.redsun.smartcrm.model.CustomerLevel;
import com.zznode.redsun.smartcrm.model.CustomerType;
import com.zznode.redsun.smartcrm.model.MonthlyIncome;
import com.zznode.redsun.smartcrm.model.PersonalHobby;
import com.zznode.redsun.smartcrm.model.PersonalInfo;
import com.zznode.redsun.smartcrm.model.Profession;
import com.zznode.redsun.smartcrm.model.Sex;

@Service
public class CustomerServiceImpl implements CustomerService {
	@Autowired
	private EntityManager entityManager;

	@Autowired
	private JdbcFinderManager jdbcFinderManager;

	@Autowired
	private JdbcDictService jdbcDictService;

	@Override
	public CustomerDto get(Long id) {
		if (null != id) {
			Customer instance = entityManager.get(Customer.class, id);
			CustomerDto dto = CustomerDto.create(instance);

			return dto;
		}
		return null;
	}

	@Override
	public void save(CustomerDto customer, LoginUser<Long> currentUser) {
		Assert.notNull(customer, "Save instance can't be null.");
		if (null != customer.getId()) {
			Customer instance = entityManager.get(Customer.class, customer.getId());
			customer.update(instance);
			entityManager.update(instance);
		} else {
			Customer instance = customer.convert();
			instance.setCreateUser(entityManager.get(PersonalInfo.class, currentUser.getUserId()));
			this.entityManager.save(instance.getPersonalInfo());
			this.entityManager.save(instance);
		}
	}

	@Override
	public Page<JSONObject> queryForPage(CustomerQuery params, int pageNumber, int pageSize) {
		String querySql = jdbcFinderManager.getQueryStringByStatementKey("CustomerService_queryForPage");
		MapCreaterBuilder builder = MapCreaterBuilder.create();

		if (null != params) {
			querySql = params.buildSql(querySql, builder);
		}

		Page<JSONObject> queryResult = jdbcFinderManager.queryForPage(querySql, builder.map(),
				new CustomerJsonRowMapper(), pageNumber, pageSize);
		return queryResult;
	}

	class CustomerJsonRowMapper implements RowMapper<JSONObject> {

		@Override
		public JSONObject mapRow(ResultSet rs, int arg1) throws SQLException {
			JSONObject instance = new JSONObject();
			instance.element("id", rs.getString("id"));
			instance.element("code", rs.getString("code"));
			instance.element("name", rs.getString("name"));
			instance.element("createDateString", GlobalUtils.formartDateTime(rs.getTimestamp("create_date")));

			String levelId = rs.getString("level_id");
			if (StringUtils.hasText(levelId)) {
				instance.element("levelId", levelId);
				instance.element("levelName", entityManager.get(CustomerLevel.class, levelId).getName());
			}

			String typeId = rs.getString("type_id");
			if (StringUtils.hasText(typeId)) {
				instance.element("typeId", typeId);
				instance.element("typeName", entityManager.get(CustomerType.class, typeId).getName());
			}

			String incomeId = rs.getString("monthly_income");
			if (StringUtils.hasText(incomeId)) {
				instance.element("incomeId", incomeId);
				instance.element("incomeName", entityManager.get(MonthlyIncome.class, incomeId).getName());
			}

			String professionId = rs.getString("profession_id");
			if (StringUtils.hasText(professionId)) {
				instance.element("professionId", professionId);
				instance.element("professionName", entityManager.get(Profession.class, professionId).getName());
			}

			String cardCategoryId = rs.getString("card_category");
			if (StringUtils.hasText(cardCategoryId)) {
				instance.element("cardCategory", cardCategoryId);
				instance.element("cardCategoryName", entityManager.get(CardCategory.class, cardCategoryId).getName());
			}

			instance.element("createUserId", rs.getString("create_user"));
			instance.element("createUserName", entityManager.get(PersonalInfo.class, instance.getLong("createUserId"))
					.getName());

			instance.element("cardNumber", rs.getString("card_number"));
			instance.element("reveiveDoc", rs.getBoolean("receive_doc"));
			instance.element("personalId", rs.getString("personal_id"));
			instance.element("sex", Sex.values()[rs.getInt("sex")]);
			Calendar birthday = Calendar.getInstance();
			birthday.setTime(rs.getDate("birthday"));
			instance.element("birthdayString", GlobalUtils.formartDate(birthday.getTime()));
			instance.element("age", Calendar.getInstance().get(Calendar.YEAR) - birthday.get(Calendar.YEAR));
			instance.element("phone1", rs.getString("phone1"));
			instance.element("phone2", rs.getString("phone2"));

			return instance;
		}

	}

	public Collection<String> getHobbies(Customer customer) {
		if (null == customer) {
			return null;
		}
		Customer instance = entityManager.get(Customer.class, customer.getId());
		Collection<String> hobbies = new ArrayList<String>();
		for (PersonalHobby entry : instance.getHobbies()) {
			hobbies.add(entry.getId());
		}
		return hobbies;
	}

	@Override
	public void fillDict(Collection<JSONObject> rows) {
		for (JSONObject entry : rows) {
			CustomerLevel level = entityManager.get(CustomerLevel.class, entry.getString("levelId"));
			entry.element("levelName", level.getName());
			CustomerType type = entityManager.get(CustomerType.class, entry.getString("typeId"));
			entry.element("typeName", type.getName());
		}
	}
}
